package com.woniu.filter;

import com.woniu.common.utils.token.AccToken;
import com.woniu.common.utils.token.JwtTokenUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 *
 * 这个过滤器主要是验证用户是否登录
 * @author 杨光 微信号:tolryg
 * @time 09:43
 */

@Component
public class AuthFilter implements GlobalFilter, Ordered {


    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    //不需要验证登录的请求url
    private static Set<String> unauthorizedUrls=new HashSet<>();
    static{
        unauthorizedUrls.add("/api/kaptcha/captchaImage");
        unauthorizedUrls.add("/api/auth/login");
        unauthorizedUrls.add("/api/auth/web/login");
        unauthorizedUrls.add("/api/cinema/cinema/movie/web/list");
        unauthorizedUrls.add("/api/cinema/cinema/movietype/web/list");
        unauthorizedUrls.add("/api/cinema/cinema/moviearea/web/list");
        unauthorizedUrls.add("/api/cinema/cinema/movie/dynamic/list");
        unauthorizedUrls.add("/api/cinema/cinema/brand/web/list");
        unauthorizedUrls.add("/api/cinema/cinema/halltype/web/list");
        unauthorizedUrls.add("/api/cinema/cinema/cinema/dynamic/list");
        unauthorizedUrls.add("/api/cinema/cinema/dashboard/web/list");
        unauthorizedUrls.add("/api/cinema/cinema/movie/web/queryMovieByMovieId");
        unauthorizedUrls.add("/api/cinema/cinema/actor/web/queryMovieActors");
        unauthorizedUrls.add("/api/cinema/cinema/movieimage/web/list");
        unauthorizedUrls.add("/api/cinema/cinema/comment/web/list");
        unauthorizedUrls.add("/api/user/web/generateCellphoneCode");
        unauthorizedUrls.add("/api/user/web/register");
        unauthorizedUrls.add("/api/cinema/cinema/cinema/web/queryById");
        unauthorizedUrls.add("/api/cinema/cinema/hallmovie/web/queryHallMovieByCinemaId");
        unauthorizedUrls.add("/api/search/web/search/movie/list");
        unauthorizedUrls.add("/api/search/web/search/actor/list");
        unauthorizedUrls.add("/api/search/web/search/cinema/list");
    }
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        String path = exchange.getRequest().getPath().toString();

        List<String> authorization = exchange.getRequest().getHeaders().get("Authorization");
        if(unauthorizedUrls.contains(path)){
            return chain.filter(exchange);
        }

        //验证jwt是否有效
        if(authorization==null){
            //圈复杂度。。。。。
            //没有请求头，则报错 401
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();

        }
        String jwtToken = authorization.get(0);
        //去掉前面的Bearer
        jwtToken = jwtToken.substring(7);
        System.out.println("jwtToken = " + jwtToken);
        //验证jwt是否有效
        //判断请求是否从portal过来
        AccToken accToken =null;
        if(path.contains("/web/") || path.contains("/dynamic/")){
            accToken = JwtTokenUtils.parseWebToken(jwtToken);
        }else{
            accToken = JwtTokenUtils.parseToken(jwtToken);
        }

        if(accToken==null){
            //没有请求头，则报错 401
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();

        }

        String redisPrefix = "";

        if(path.contains("/web/") || path.contains("/dynamic/")){
            redisPrefix = "webToken_";

        }else{
            redisPrefix = "token_";
        }

        String cachedToken = stringRedisTemplate.opsForValue().get(redisPrefix+accToken.getUserId());
        if(jwtToken.equals(cachedToken)){
            stringRedisTemplate.opsForValue().set(redisPrefix+accToken.getUserId(), jwtToken, 30, TimeUnit.MINUTES);
        }else{
            //没有请求头，则报错 401
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }

        //把user信息从Token获取，并传给后续的微服务使用
        ServerHttpRequest request = exchange.getRequest().mutate()
                .header("userId", accToken.getUserId() + "")
                .header("userAccount", accToken.getUserAccount())
                .header("userName", accToken.getUserName()).build();

        return chain.filter(exchange.mutate().request(request).build());
    }

    @Override
    public int getOrder() {
        return 0;
    }
}
